home *** CD-ROM | disk | FTP | other *** search
/ Suzy B Software 2 / Suzy B Software CD-ROM 2 (1994).iso / extras / programm / gemfsc20 / gemfsc20.lzh / GEMFUNCS / OBJ_DRAW.C < prev    next >
C/C++ Source or Header  |  1993-03-20  |  20KB  |  687 lines

  1. /*****************************************************************************
  2.  * OBJ_DRAW.C - A reentrant objc_draw() that is limited to certain ob_types.
  3.  *
  4.  *    This can do STRINGS, BUTTONS, BOXES, TEXT.
  5.  *    It cannot do FTEXT, IMAGES, ICONS, or the newer 3D-style objects.
  6.  *    It can render ob_states of SELECTED, OUTLINED, and DISABLED.
  7.  *    It cannot do SHADOWED, CHECKED or CROSSED.
  8.  *
  9.  *    A special object type, G_RSTRING is also supported.  This is a string
  10.  *    object that completely replaces an existing string; think of it as a
  11.  *    bordeless opaque background-filled left-justified BOXTEXT object.
  12.  *
  13.  *    Other than the above limitations, it behaves just like objc_draw.  It
  14.  *    exists primarily to support some of the new extended GemFast objects
  15.  *    such as the text scroller and numeric slider.
  16.  ****************************************************************************/
  17.  
  18. #include "gemfintl.h"
  19.  
  20. /*----------------------------------------------------------------------------
  21.  * constants defining interior, border, and text colors for stock objects.
  22.  *--------------------------------------------------------------------------*/
  23.  
  24. #define DEFAULT_COLORS        0x1180
  25. #define OUTLINED_COLORS     0x0000
  26. #define SELECTED_COLORS     0x0071
  27. #define DISABLED_COLORS     0x0040
  28.  
  29. static short sysfont_height = 0;
  30.  
  31. /*----------------------------------------------------------------------------
  32.  * internal parm block, passed to all internal functions.
  33.  *     this is just a bunch of data that all the low-level functions need,
  34.  *     all glommed together in one structure so we can pass it around quickly.
  35.  *     (eat your heart out Jim, I still think this is a Good Idea. ::grin::)
  36.  *--------------------------------------------------------------------------*/
  37.  
  38. typedef struct internal_parm_block {
  39.     short    vhandle;    /* handle of VDI shared workstation.                */
  40.     GRECT    gdrawrect;    /* rectangle of object currently being rendered.    */
  41.     VRECT    vdrawrect;    /* same drawing rectangle, pre-converted to VRECT.    */
  42.     GRECT    gcliprect;    /* clipping rectangle specified in objc_draw() call.*/
  43.     VRECT    vcliprect;    /* same clipping rectangle, pre-converted to VRECT. */
  44.     short    obtype;     /* current object's type, w/extended type stripped. */
  45.     short    color;        /* current object's color word.                     */
  46.     short    frame_width;/* current object's border width.                   */
  47.     union {             /* current object's ob_spec, after processing       */
  48.       long       lval;    /* INDIRECT flag (if present).                        */
  49.       char       *pstring;/*                                                    */
  50.       TEDINFO  *pted;    /*                                                    */
  51.       XUSERBLK *pub;
  52.     }        obspec;
  53. } IPB;
  54.  
  55. /*----------------------------------------------------------------------------
  56.  * internal functions...
  57.  *--------------------------------------------------------------------------*/
  58.  
  59. #ifdef GEMFAST_PROTOS
  60.  
  61.   INTERNAL_VFUNC draw_shadow(IPB * pb, short color, short width);
  62.   INTERNAL_VFUNC draw_frame(IPB * pb, short color, short width);
  63.   INTERNAL_VFUNC draw_interior(IPB * pb, short color);
  64.   INTERNAL_VFUNC draw_text(IPB * pb, short color, short justify, short font, char *string);
  65.   INTERNAL_VFUNC render_box(IPB * pb);
  66.   INTERNAL_VFUNC render_string(IPB * pb);
  67.   INTERNAL_VFUNC render_button(IPB * pb);
  68.   INTERNAL_VFUNC render_text(IPB * pb);
  69.   INTERNAL_IFUNC render_userdef(IPB * pb, OBJECT *ptree, short obj, short prevstate, short currstate);
  70.   INTERNAL_VFUNC render_obstate(IPB *pb, short obstate);
  71.   INTERNAL_VFUNC render_object(IPB *pb, OBJECT *ptree, short obj, short xoff, short yoff);
  72.   INTERNAL_VFUNC render_tree(IPB *pb, OBJECT *ptree, short obj, short depth, short do_siblings, short xoff, short yoff);
  73.   INTERNAL_IFUNC special_render_selected_state(OBJECT *ptree, short obj, GRECT *cliprect);
  74.  
  75. #endif
  76.  
  77. #if 0 /* de-implement this for now */
  78.  
  79. INTERNAL_VFUNC draw_shadow(pb, color, width)
  80.     IPB *    pb;
  81.     short    color;
  82.     short    width;
  83. /*----------------------------------------------------------------------------
  84.  * draw a shadow under and to the right of an object.
  85.  *     this doesn't do AES-style shadows, it does real-looking ones. :-)
  86.  *--------------------------------------------------------------------------*/
  87. {
  88.     short    pxy[12];
  89.     short    x;
  90.     short    y;
  91.     short    hbox2;
  92.     short    wbox2;
  93.     short    medrez_kludge;
  94.  
  95.     wbox2 = gl_wbox / 2;
  96.     hbox2 = gl_hbox / 2;
  97.  
  98.     x = pb->vdrawrect.v_x2;
  99.     y = pb->vdrawrect.v_y2;
  100.  
  101.     if (width == 0) {
  102.         return;
  103.     } else if (width < 0) {
  104.         x -= width;
  105.         y -= width;
  106.     }
  107.  
  108.     if (gl_rfscrn.g_w >= 640 && gl_rfscrn.g_h <= 200) {
  109.         medrez_kludge = 3;    /* this adjusts for bogus medrez aspect ratio    */
  110.     } else {
  111.         medrez_kludge = 0;
  112.     }
  113.  
  114.     pxy[0]    =  pxy[2]  =  pb->vdrawrect.v_x1 + wbox2 / 2;
  115.     pxy[1]    =  pxy[11] =  y;
  116.     pxy[3]    =  pxy[5]  =  y + hbox2;
  117.     pxy[4]    =  pxy[6]  =  x + wbox2 - medrez_kludge;
  118.     pxy[7]    =  pxy[9]  =  pb->vdrawrect.v_y1 + hbox2 / 2;
  119.     pxy[8]    =  pxy[10] =  x;
  120.  
  121.     color >>= 12;
  122.  
  123.     if (color != 1) {
  124.         vsf_color(pb->vhandle, color);
  125.     }
  126.  
  127.     vswr_mode(pb->vhandle, MD_TRANS);
  128.     vsf_interior(pb->vhandle, IS_PATTERN);
  129.     vsf_style(pb->vhandle, 4);
  130.     vsf_perimeter(pb->vhandle, FALSE);
  131.  
  132.     v_fillarea(pb->vhandle, 6, pxy);    /* draw L-shaped shadow             */
  133.  
  134.     vswr_mode(pb->vhandle, MD_REPLACE);
  135.     vsf_interior(pb->vhandle, IS_SOLID);
  136.     vsf_style(pb->vhandle, 8);
  137.     vsf_perimeter(pb->vhandle, TRUE);
  138.  
  139.     if (color != 1) {
  140.         vsf_color(pb->vhandle, 1);
  141.     }
  142.  
  143. }
  144.  
  145. #endif /* end of de-implemented shadow rendering */
  146.  
  147. INTERNAL_VFUNC draw_frame(pb, color, width)
  148.     IPB *    pb;
  149.     short    color;
  150.     short    width;
  151. /*----------------------------------------------------------------------------
  152.  * draw a frame (ibox) of a given line width.
  153.  *--------------------------------------------------------------------------*/
  154. {
  155.     short    pxy[10];
  156.     short    adjust;
  157.     short    direction;
  158.  
  159.     if (width == 0) {
  160.         return;
  161.     } else if (width < 0) {
  162.         direction = 1;
  163.         adjust      = width;
  164.     } else {
  165.         direction = -1;
  166.         adjust      = width - 1;
  167.     }
  168.  
  169.     color >>= 12;
  170.  
  171.     if (color != 1) {
  172.         vsl_color(pb->vhandle, color);
  173.     }
  174.  
  175.     while (width) {
  176.         pxy[0] = pxy[6] = pxy[8] = pb->vdrawrect.v_x1 + adjust;
  177.         pxy[1] = pxy[3] = pxy[9] = pb->vdrawrect.v_y1 + adjust;
  178.         pxy[2] = pxy[4] =           pb->vdrawrect.v_x2 - adjust;
  179.         pxy[5] = pxy[7] =           pb->vdrawrect.v_y2 - adjust;
  180.         v_pline(pb->vhandle, 5, pxy);
  181.         adjust += direction;
  182.         width  += direction;
  183.     }
  184.  
  185.     if (color != 1) {
  186.         vsl_color(pb->vhandle, 1);
  187.     }
  188. }
  189.  
  190. INTERNAL_VFUNC draw_interior(pb, color)
  191.     IPB *    pb;
  192.     short    color;
  193. /*----------------------------------------------------------------------------
  194.  * draw the interior of a box.
  195.  *--------------------------------------------------------------------------*/
  196. {
  197.     short style;
  198.  
  199.     style  = (color >> 4) & 0x0007;
  200.     color &= 0x000F;
  201.  
  202.     if (color != 1) {
  203.         vsf_color(pb->vhandle, color);
  204.     }
  205.  
  206.     switch (style) {
  207.       case 0:
  208.         vsf_interior(pb->vhandle, IS_HOLLOW);
  209.         break;
  210.       case 7:
  211.         break;    /* style 7 is the default already set on the workstation    */
  212.       default:
  213.         vsf_interior(pb->vhandle, IS_PATTERN);
  214.         vsf_style(pb->vhandle, style);
  215.         break;
  216.     }
  217.  
  218.     vr_recfl(pb->vhandle, (short *)&pb->vdrawrect);
  219.  
  220.     if (color != 1) {
  221.         vsf_color(pb->vhandle, 1);
  222.     }
  223.  
  224.     if (style != 7) {
  225.         vsf_interior(pb->vhandle, IS_SOLID);
  226.         vsf_style(pb->vhandle, 8);
  227.     }
  228. }
  229.  
  230. INTERNAL_VFUNC draw_text(pb, color, justify, font, string)
  231.     IPB *    pb;
  232.     short    color;
  233.     short    justify;
  234.     short    font;
  235.     char    *string;
  236. /*----------------------------------------------------------------------------
  237.  * draw some text; will clip text to object's boundaries.
  238.  *--------------------------------------------------------------------------*/
  239. {
  240.     short    mode;
  241.     short    wchar;
  242.     short    hchar;
  243.     short    textwidth;
  244.     short    dmy;
  245.     short    x;
  246.     short    y;
  247.     GRECT    gcliprect;
  248.     VRECT    vcliprect;
  249.  
  250.     mode  = color & 0x0080;
  251.     color = (color >> 8) & 0x000F;
  252.  
  253.     if (color != 1) {
  254.         vst_color(pb->vhandle, color);
  255.     }
  256.     if (mode == 0) {
  257.         vswr_mode(pb->vhandle, MD_TRANS);
  258.     }
  259.     if (font == TE_SMALL) {
  260.         vst_height(pb->vhandle, 4, &wchar, &hchar, &dmy, &dmy);
  261.     } else {
  262.         wchar = gl_wchar;
  263.         hchar = gl_hchar;
  264.     }
  265.  
  266.     textwidth = wchar * (short)strlen(string);
  267.     switch (justify) {
  268.         case TE_LEFT:
  269.             x = pb->gdrawrect.g_x;
  270.             break;
  271.         case TE_RIGHT:
  272.             x = pb->gdrawrect.g_x + (pb->gdrawrect.g_w - textwidth);
  273.             break;
  274.         case TE_CNTR:
  275.             x = pb->gdrawrect.g_x + ((pb->gdrawrect.g_w - textwidth) / 2);
  276.             break;
  277.     }
  278.     y = pb->gdrawrect.g_y + ((pb->gdrawrect.g_h - hchar) / 2);
  279.     vst_alignment(pb->vhandle, 0, 5, &dmy, &dmy);
  280.  
  281.     gcliprect = pb->gcliprect;
  282.     if (rc_intersect(&pb->gdrawrect, &gcliprect)) {
  283.         rc_gtov(&gcliprect, &vcliprect);
  284.         vs_clip(pb->vhandle, TRUE, (short *)&vcliprect);
  285.         v_gtext(pb->vhandle, x, y, string);
  286.         vs_clip(pb->vhandle, TRUE, (short *)&pb->vcliprect);
  287.     }
  288.  
  289.     vst_alignment(pb->vhandle, 0, 0, &dmy, &dmy);
  290.  
  291.     if (color != 1) {
  292.         vst_color(pb->vhandle, 1);
  293.     }
  294.     if (mode == 0) {
  295.         vswr_mode(pb->vhandle, MD_REPLACE);
  296.     }
  297.     if (font == TE_SMALL) {
  298.         vst_height(pb->vhandle, sysfont_height, &dmy, &dmy, &dmy, &dmy);
  299.     }
  300. }
  301.  
  302. INTERNAL_VFUNC render_box(pb)
  303.     IPB *    pb;
  304. /*----------------------------------------------------------------------------
  305.  * render a box, ibox, or boxchar object.
  306.  *--------------------------------------------------------------------------*/
  307. {
  308.     char    str[2];
  309.  
  310.     if (pb->obtype != G_IBOX) {
  311.         draw_interior(pb, pb->color);
  312.     }
  313.  
  314.     if (pb->obtype == G_BOXCHAR) {
  315.         str[0] = (char)(pb->obspec.lval >> 24);
  316.         str[1] = 0;
  317.         draw_text(pb, pb->color, TE_CNTR, TE_SYSTEM, str);
  318.     }
  319.  
  320.     draw_frame(pb, pb->color, pb->frame_width);
  321.  
  322. }
  323.  
  324. INTERNAL_VFUNC render_string(pb)
  325.     IPB * pb;
  326. /*----------------------------------------------------------------------------
  327.  * render a string or title object.
  328.  *--------------------------------------------------------------------------*/
  329. {
  330.     if (pb->obtype == G_RSTRING) {            /* special object: replace string,*/
  331.         draw_interior(pb, DEFAULT_COLORS);    /* it's like a borderless boxtext;*/
  332.     }                                        /* erases existing string.        */
  333.  
  334.     draw_text(pb, DEFAULT_COLORS, TE_LEFT, TE_SYSTEM, pb->obspec.pstring);
  335. }
  336.  
  337. INTERNAL_VFUNC render_button(pb)
  338.     IPB * pb;
  339. /*----------------------------------------------------------------------------
  340.  * render a button object.
  341.  *--------------------------------------------------------------------------*/
  342. {
  343.     draw_interior(pb, DEFAULT_COLORS);
  344.     draw_text(pb, DEFAULT_COLORS, TE_CNTR, TE_SYSTEM, pb->obspec.pstring);
  345.     draw_frame(pb, DEFAULT_COLORS, pb->frame_width);
  346. }
  347.  
  348. INTERNAL_VFUNC render_text(pb)
  349.     IPB * pb;
  350. /*----------------------------------------------------------------------------
  351.  * render a text or boxtext (but not ftext or fboxtext) object.
  352.  *--------------------------------------------------------------------------*/
  353. {
  354.     TEDINFO *pted = pb->obspec.pted;
  355.  
  356.     if (pb->obtype == G_BOXTEXT) {
  357.         draw_interior(pb, pb->color);
  358.     }
  359.  
  360.     draw_text(pb, pb->color, pted->te_just, pted->te_font, pted->te_ptext);
  361.  
  362.     if (pb->obtype == G_BOXTEXT) {
  363.         draw_frame(pb, pb->color, pb->frame_width);
  364.     }
  365. }
  366.  
  367. INTERNAL_IFUNC render_userdef(pb, ptree, obj, prevstate, currstate)
  368.     IPB *    pb;
  369.     OBJECT *ptree;
  370.     short    obj;
  371.     short    prevstate;
  372.     short    currstate;
  373. /*----------------------------------------------------------------------------
  374.  * render a userdef object, return unrendered-state info from user draw func.
  375.  *--------------------------------------------------------------------------*/
  376. {
  377.     XPARMBLK    xpb;    /* a standard PARMBLK with sensibly-typed fields    */
  378.  
  379.     xpb.ptree        = ptree;
  380.     xpb.obj         = obj;
  381.     xpb.prevstate    = prevstate;
  382.     xpb.currstate    = currstate;
  383.     xpb.drawrect    = pb->gdrawrect;
  384.     xpb.cliprect    = pb->gcliprect;
  385.     xpb.pub         = pb->obspec.pub;
  386.  
  387.     return (int)(*pb->obspec.pub->ub_draw)(&xpb);
  388. }
  389.  
  390. INTERNAL_VFUNC render_obstate(pb, obstate)
  391.     IPB *    pb;
  392.     short    obstate;
  393. /*----------------------------------------------------------------------------
  394.  * render the object state effects.
  395.  *--------------------------------------------------------------------------*/
  396. {
  397.     if (obstate & OUTLINED) {
  398.         draw_frame(pb, DEFAULT_COLORS, -3);
  399.         draw_frame(pb, OUTLINED_COLORS, -2);
  400.     }
  401.  
  402. /*    if (obstate & SHADOWED) {                                                */
  403. /*       draw_shadow(pb, pb->color, pb->frame_width);                         */
  404. /*    }                                                                        */
  405.  
  406.     if (obstate & SELECTED) {
  407.         vswr_mode(pb->vhandle, MD_XOR);
  408.         draw_interior(pb, SELECTED_COLORS);
  409.         vswr_mode(pb->vhandle, MD_REPLACE);
  410.     }
  411.  
  412.     if (obstate & DISABLED) {
  413.         vswr_mode(pb->vhandle, MD_ERASE);
  414.         draw_interior(pb, DISABLED_COLORS);
  415.         vswr_mode(pb->vhandle, MD_REPLACE);
  416.     }
  417.  
  418.     if (obstate & CHECKED) {    /* really should do this one next            */
  419.     }
  420.  
  421.     if (obstate & CROSSED) {    /* everyone's favorite state                */
  422.     }
  423.  
  424. }
  425.  
  426. INTERNAL_VFUNC render_object(pb, ptree, obj, xoff, yoff)
  427.     IPB *    pb;
  428.     OBJECT *ptree;
  429.     short    obj;
  430.     short    xoff;
  431.     short    yoff;
  432. /*----------------------------------------------------------------------------
  433.  * render a single object of any (currently supported) type.
  434.  *--------------------------------------------------------------------------*/
  435. {
  436.     OBJECT    *pobj;
  437.     short    obstate;
  438.  
  439.     pobj = &ptree[obj];
  440.     obstate = pobj->ob_state;
  441.  
  442.     pb->gdrawrect.g_x = pobj->ob_x + xoff;
  443.     pb->gdrawrect.g_y = pobj->ob_y + yoff;
  444.     pb->gdrawrect.g_w = pobj->ob_width;
  445.     pb->gdrawrect.g_h = pobj->ob_height;
  446.  
  447.     rc_gtov(&pb->gdrawrect, &pb->vdrawrect);
  448.  
  449.     if (pobj->ob_flags & INDIRECT) {
  450.         pb->obspec.lval = *(long*)pobj->ob_spec;
  451.     } else {
  452.         pb->obspec.lval = (long)pobj->ob_spec;
  453.     }
  454.  
  455.     pb->frame_width = 0;
  456.     pb->color        = DEFAULT_COLORS;
  457.     pb->obtype        = pobj->ob_type & 0x00FF;
  458.  
  459.     switch (pb->obtype) {
  460.       case G_BOX:
  461.       case G_IBOX:
  462.       case G_BOXCHAR:
  463.         pb->frame_width = (char)(pb->obspec.lval >> 16);
  464.         pb->color        = (short)(pb->obspec.lval & 0x0000FFFF);
  465.         render_box(pb);
  466.         break;
  467.       case G_TEXT:
  468.       case G_BOXTEXT:
  469.         pb->frame_width = pb->obspec.pted->te_thickness;
  470.         pb->color        = pb->obspec.pted->te_color;
  471.         render_text(pb);
  472.         break;
  473.       case G_BUTTON:
  474.         pb->frame_width = -1;
  475.         if (pobj->ob_flags & EXIT) {
  476.             --pb->frame_width;
  477.             if (pobj->ob_flags & DEFAULT) {
  478.                 --pb->frame_width;
  479.             }
  480.         }
  481.         render_button(pb);
  482.         break;
  483.       case G_TITLE:
  484.       case G_STRING:
  485.       case G_RSTRING:
  486.         render_string(pb);
  487.         break;
  488.       case G_USERDEF:
  489.         obstate = render_userdef(pb, ptree, obj, obstate, obstate);
  490.         break;
  491.     }
  492.  
  493.     render_obstate(pb, obstate);
  494. }
  495.  
  496. INTERNAL_VFUNC render_tree(pb, ptree, obj, depth, do_siblings, xoff, yoff)
  497.     IPB *    pb;
  498.     OBJECT *ptree;
  499.     short    obj;
  500.     short    depth;
  501.     short    do_siblings;
  502.     short    xoff;
  503.     short    yoff;
  504. /*----------------------------------------------------------------------------
  505.  * render all objects in the tree/subtree, recursing to specified depth.
  506.  *--------------------------------------------------------------------------*/
  507. {
  508.     OBJECT    *pobj;
  509.     short    nxtobj;
  510.  
  511.     do    {
  512.         pobj = &ptree[obj];
  513.         if (!(pobj->ob_flags & HIDETREE)) {
  514.             render_object(pb, ptree, obj, xoff, yoff);
  515.             nxtobj = pobj->ob_head;
  516.             if (depth > 1 && nxtobj != NO_OBJECT) {
  517.                 render_tree(pb, ptree, nxtobj, depth-1, TRUE,
  518.                             xoff+ptree[obj].ob_x, yoff+ptree[obj].ob_y);
  519.             }
  520.         }
  521.         if (!do_siblings) {
  522.             obj = NO_OBJECT;
  523.         } else {
  524.             nxtobj = pobj->ob_next;
  525.             if (nxtobj == NO_OBJECT || ptree[nxtobj].ob_tail == obj) {
  526.                 obj = NO_OBJECT;
  527.             } else {
  528.                 obj = nxtobj;
  529.             }
  530.         }
  531.     } while (obj != NO_OBJECT);
  532. }
  533.  
  534. INTERNAL_IFUNC special_render_selected_state(ptree, obj, cliprect)
  535.     OBJECT *ptree;
  536.     short    obj;
  537.     GRECT *cliprect;
  538. /*----------------------------------------------------------------------------
  539.  * render a change in the SELECTED state.
  540.  *     this is a special speedup kludge for obj__change().  the state most
  541.  *     often changed is SELECTED, and for things like menu displays our
  542.  *     standard logic of erasing and redrawing the object is a bit slow; the
  543.  *     visual effect isn't very pleasing.  so, if the only state being
  544.  *     changed on an obj__change call is SELECTED, we come here and XOR the
  545.  *     object's interior quickly, instead of using the erase-and-redraw logic.
  546.  *--------------------------------------------------------------------------*/
  547. {
  548.     IPB     pb;
  549.  
  550.     if (0 == (pb.vhandle = apl_vshared())) {
  551.         return FALSE;
  552.     }
  553.  
  554.     obj_offxywh(ptree, obj, &pb.gdrawrect);
  555.     rc_gtov(&pb.gdrawrect, &pb.vdrawrect);
  556.  
  557.     pb.gcliprect = *cliprect;
  558.  
  559.     if (rc_intersect(&gl_rfscrn, &pb.gcliprect)) {
  560.         rc_gtov(&pb.gcliprect, &pb.vcliprect);
  561.         v_hide_c(pb.vhandle);
  562.         vs_clip(pb.vhandle, TRUE, (short *)&pb.vcliprect);
  563.         vswr_mode(pb.vhandle, MD_XOR);
  564.         draw_interior(&pb, SELECTED_COLORS);
  565.         vswr_mode(pb.vhandle, MD_REPLACE);
  566.         vs_clip(pb.vhandle, FALSE, (short *)&pb.vcliprect);
  567.         v_show_c(pb.vhandle, TRUE);
  568.     }
  569.  
  570.     return TRUE;
  571. }
  572.  
  573. /*----------------------------------------------------------------------------
  574.  * public functions...
  575.  *--------------------------------------------------------------------------*/
  576.  
  577. int obj__offset(ptree, obj, px, py)
  578.     OBJECT *ptree;
  579.     short    obj;
  580.     short * px;
  581.     short * py;
  582. /*****************************************************************************
  583.  * return screen-adjusted object coordinates.
  584.  ****************************************************************************/
  585. {
  586.     short    x = 0;
  587.     short    y = 0;
  588.  
  589.     while (obj != ROOT) {
  590.         x  += ptree[obj].ob_x;
  591.         y  += ptree[obj].ob_y;
  592.         obj = obj_parent(ptree, obj);
  593.     }
  594.  
  595.     *px = x + ptree->ob_x;;
  596.     *py = y + ptree->ob_y;
  597.  
  598.     return TRUE;
  599. }
  600.  
  601. short obj__draw(ptree, obj, depth, cliprect)
  602.     OBJECT *ptree;
  603.     short    obj;
  604.     short    depth;
  605.     GRECT * cliprect;
  606. /*****************************************************************************
  607.  * draw object tree, as per AES function objc_draw().
  608.  ****************************************************************************/
  609. {
  610.     IPB     pb;
  611.     short    xoff, yoff;
  612.  
  613.     if (0 == (pb.vhandle = apl_vshared())) {
  614.         return FALSE;
  615.     }
  616.  
  617.     if (sysfont_height == 0) {
  618.         short attr[10];
  619.         vqt_attributes(pb.vhandle, attr);
  620.         sysfont_height = attr[7];
  621.     }
  622.  
  623.     pb.gcliprect = *cliprect;
  624.  
  625.     if (obj == ROOT) {
  626.         xoff = yoff = 0;
  627.     } else {
  628.         objc_offset(ptree, obj_parent(ptree, obj), &xoff, &yoff);
  629.     }
  630.  
  631.     if (rc_intersect(&gl_rfscrn, &pb.gcliprect)) {
  632.         rc_gtov(&pb.gcliprect, &pb.vcliprect);
  633.         v_hide_c(pb.vhandle);
  634.         vs_clip(pb.vhandle, TRUE, (short *)&pb.vcliprect);
  635.         render_tree(&pb, ptree, obj, depth, FALSE, xoff, yoff);
  636.         vs_clip(pb.vhandle, FALSE, (short *)&pb.vcliprect);
  637.         v_show_c(pb.vhandle, TRUE);
  638.     }
  639.  
  640.     return TRUE;
  641. }
  642.  
  643. int obj__change(ptree, obj, reserved, cliprect, newstate, redraw)
  644.     OBJECT *ptree;
  645.     short    obj;
  646.     short    reserved;
  647.     GRECT * cliprect;
  648.     short    newstate;
  649.     short    redraw;
  650. /*****************************************************************************
  651.  * change an object's ob_state, with optional redraw.
  652.  *    this does NOT work like the AES's equivelent function.  this one
  653.  *    always redraws the object in its entirety.    in addition, the redraw
  654.  *    starts with the object's parent and is clipped such that the bits
  655.  *    outside the object (ie, OUTLINED and SHADOWED) are properly redrawn.
  656.  *
  657.  *    if the only state being changed is SELECTED, we use special logic to
  658.  *    quickly XOR the object's interior instead of using the erase-and-redraw
  659.  *    logic.    this gives a better visual effect on things like menus where
  660.  *    the SELECTED state is changed rapidly while tracking the mouse.
  661.  ****************************************************************************/
  662. {
  663.     short    oldstate;
  664.     GRECT    userclip;
  665.     GRECT    objclip;
  666.  
  667.     oldstate = ptree[obj].ob_state;
  668.     ptree[obj].ob_state = newstate;
  669.  
  670.     if (!redraw || oldstate == newstate) {
  671.         return TRUE;
  672.     }
  673.  
  674.     if ((oldstate ^ newstate) == SELECTED) {
  675.         return special_render_selected_state(ptree, obj, cliprect);
  676.     }
  677.  
  678.     userclip = *cliprect;
  679.     obj_clcalc(ptree, obj, &objclip, NULL);
  680.     if (rc_intersect(&userclip, &objclip)) {
  681.         obj = obj_parent(ptree, obj);
  682.         return objc_draw(ptree, obj, MAX_DEPTH, RECTVALS(&objclip));
  683.     }
  684. }
  685.  
  686.  
  687.